package club.kingyin.context;

import club.kingyin.annotation.Aspect;
import club.kingyin.annotation.Scan;
import club.kingyin.component.BeanDefinitionClassPathScanner;
import club.kingyin.component.DefaultBeanDefinitionRegister;
import club.kingyin.core.*;
import club.kingyin.test.UserService;

import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Objects;

/**
 * @author : kingyins
 * @version : 1.0
 * @program : my-spring
 * @description : 注解Context
 * @create : 2021年07月19日 15:25
 **/

public class AnnotationConfigApplicationContext extends AbstractApplicationContext{


    private String path;
    private BeanDefinitionClassPathScanner scanner;

    public AnnotationConfigApplicationContext() {
        // 设置处理器
        prepareBeanFactory(this);
        // 设置注册器
        setBeanDefinitionRegistry(new DefaultBeanDefinitionRegister());
        // 设置扫描器
        scanner = new BeanDefinitionClassPathScanner(path);
    }

    public AnnotationConfigApplicationContext(Class<?> configContext) {
        Scan scan = configContext.getDeclaredAnnotation(Scan.class);
        path = scan.value();
        System.out.println("获取扫描路径："+path);
        // 设置处理器
        prepareBeanFactory(this);
        // 设置注册器
        setBeanDefinitionRegistry(new DefaultBeanDefinitionRegister());
        // 设置扫描器
        scanner = new BeanDefinitionClassPathScanner(path);
        refresh();
    }

    public int scan(String ... packages) {
        return scanner.scan(this, packages);
    }

    @Override
    public void registerBeanPostProcessors() {
        beanPostProcessorSet.add(new BeanPostProcessor() {
            @Override
            public Object PostProcessorBeforeInitialization(Object bean, String beanName) {
                System.out.println(beanName+"初始化前");
                return bean;
            }
        });
        beanPostProcessorSet.add(new BeanPostProcessor() {
            @Override
            public Object PostProcessorAfterInitialization(Object bean, String beanName) {
                System.out.println(beanName+"初始化后");
                Class<?> beanClass = bean.getClass();
                if (beanClass.isAnnotationPresent(Aspect.class)) {
                    Class<?>[] interfaces = beanClass.getInterfaces();
                    if (interfaces.length > 0) {
                        Aspect aspect = beanClass.getDeclaredAnnotation(Aspect.class);
                        // 代理失败 原因未知 只显示代理结果为空指针？
//                        Object finalBean = bean;
//                        bean = Proxy.newProxyInstance(bean.getClass().getClassLoader(), interfaces, (proxy, method, args) -> {
//                            Class<? extends AspectProxy>[] value = aspect.value();
//                            AspectProxy[] aspectProxies = new AspectProxy[value.length];
//                            Reference<AspectProxy[]> reference = new SoftReference<>(aspectProxies);
//                            int index = 0;
//                            // 前置
//                            for (Class<? extends AspectProxy> aClass : value) {
//                                // 实例化增强接口
//                                AspectProxy aspectProxy = aClass.newInstance();
//                                // 软引用
//                                Objects.requireNonNull(reference.get())[index++] = aspectProxy;
//                                // 具体增强方法
//                                args = aspectProxy.before(method.getName(), args);
//                            }
//                            // 方法调用
//                            Object res = method.invoke(finalBean,args);
//                            // 后置
//                            for (AspectProxy aspectProxy : Objects.requireNonNull(reference.get())) {
//                                // 具体增强方法
//                                res = aspectProxy.after(method.getName(), res);
//                            }
//                            return res;
//                        });
//
                    }
                }
                return bean;
            }
        });
        beanPostProcessorSet.add(new InstantiationAwareBeanPostProcessor() {
            @Override
            public BeanDefinition postProcessorBeforeInstantiation(BeanDefinition mbd, String beanName) {
                System.out.println(beanName+"实例化前");
                return mbd;
            }
        });
        beanPostProcessorSet.add(new InstantiationAwareBeanPostProcessor() {
            @Override
            public Object postProcessorAfterInstantiation(Object bean, String beanName) {
                System.out.println(beanName+"实例化后");
                return bean;
            }
        });
    }

    /**
     * BeanFactory后置处理器，这里主要用于自动扫描BeanDefinition
     * 扫描完成后自动注册到容器中
     * @param beanFactory 容器
     */
    @Override
    public void postProcessBeanFactory(AbstractApplicationContext beanFactory) {
        scanner.scan(this,path);
    }


}
